package btree4j.template;

import btree4j.BTreeException;
import btree4j.Value;

import java.io.*;
import java.nio.ByteBuffer;

public class TemplateDataOperator {
    private TemplateManager templateManager;

    public TemplateDataOperator(TemplateManager templateManager) {
        this.templateManager = templateManager;
    }

    public void addData(long templateId, TemplateDataRow dataRow) throws BTreeException, IOException {
        // 获取模板定义
        Template template = templateManager.getTemplate(templateId);
        if (template == null) {
            throw new IllegalArgumentException("Template with ID " + templateId + " not found");
        }

        // 获取主键列
        Column primaryKeyColumn = null;
        for (Column column : template.getColumns()) {
            if (column.isPrimaryKey()) {
                primaryKeyColumn = column;
                break;
            }
        }
        if (primaryKeyColumn == null) {
            throw new IllegalArgumentException("Template has no primary key column");
        }

        // 获取主键值
        Object primaryKeyValue = dataRow.getColumnValue(primaryKeyColumn.getName());
        if (primaryKeyValue == null) {
            throw new IllegalArgumentException("Primary key value cannot be null");
        }

        // 序列化数据行
        byte[] dataBytes = serializeData(dataRow);

        // 插入到索引
        Value key = new Value(primaryKeyValue.toString());
        Value value = new Value(dataBytes);
        templateManager.addDataToTemplateIndex(templateId, key, value);

        // 插入二级索引
        for (String indexedColumn : template.getIndexedColumns()) {
            Object columnValue = dataRow.getColumnValue(indexedColumn);
            if (columnValue != null) {
                Value indexKey = new Value(columnValue.toString());
                templateManager.addDataToSecondaryIndex(templateId, indexedColumn, indexKey, key);
            }
        }
    }

    public void updateData(long templateId, TemplateDataRow dataRow) throws BTreeException, IOException, ClassNotFoundException {
        // 获取模板定义
        Template template = templateManager.getTemplate(templateId);
        if (template == null) {
            throw new IllegalArgumentException("Template with ID " + templateId + " not found");
        }

        // 获取主键列
        Column primaryKeyColumn = null;
        for (Column column : template.getColumns()) {
            if (column.isPrimaryKey()) {
                primaryKeyColumn = column;
                break;
            }
        }
        if (primaryKeyColumn == null) {
            throw new IllegalArgumentException("Template has no primary key column");
        }

        // 获取主键值
        Object primaryKeyValue = dataRow.getColumnValue(primaryKeyColumn.getName());
        if (primaryKeyValue == null) {
            throw new IllegalArgumentException("Primary key value cannot be null");
        }

        // 序列化数据行
        byte[] dataBytes = serializeData(dataRow);

        // 获取旧数据
        TemplateDataRow oldDataRow = getData(templateId, primaryKeyValue);
        if (oldDataRow == null) {
            throw new IllegalArgumentException("Old data row not found for primary key: " + primaryKeyValue);
        }


        // 更新索引
        Value key = new Value(primaryKeyValue.toString());
        Value newValuePrimary = new Value(dataBytes);
        templateManager.updateDataInTemplateIndex(templateId, key, newValuePrimary);

        // 处理二级索引变更
        for (String indexedColumn : template.getIndexedColumns()) {
            Object oldValue = oldDataRow.getColumnValue(indexedColumn);
            Object newValue = dataRow.getColumnValue(indexedColumn);

            if (!String.valueOf(oldValue).equals(String.valueOf(newValue))) {
                Value oldKey = oldValue != null ? new Value(oldValue.toString()) : null;
                Value newKey = new Value(newValue.toString());
                templateManager.updateSecondaryIndex(templateId, indexedColumn, oldKey, newKey, key);
            }
        }
    }

    public void removeData(long templateId, Object primaryKeyValue) throws BTreeException, IOException, ClassNotFoundException {
        Value key = new Value(primaryKeyValue.toString());

        // 1. 将主键值转换为 long 类型
        long pkLong;
        try {
            pkLong = Long.parseLong(primaryKeyValue.toString());
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("主键值无法转换为 long: " + primaryKeyValue);
        }

        // 删除二级索引
        Template template = templateManager.getTemplate(templateId);
        TemplateDataRow dataRow = getData(templateId, primaryKeyValue);
        if (dataRow != null) {
            //Value pkValue = new Value(primaryKeyValue.toString());
            for (String indexedColumn : template.getIndexedColumns()) {
                Object columnValue = dataRow.getColumnValue(indexedColumn);
                if (columnValue != null) {
                    Value indexKey = new Value(columnValue.toString());
                    templateManager.removeDataFromSecondaryIndex(templateId, indexedColumn, indexKey, pkLong);
                }
            }
        }

        templateManager.removeDataFromTemplateIndex(templateId, key);
    }

    public TemplateDataRow getData(long templateId, Object primaryKeyValue) throws BTreeException, IOException, ClassNotFoundException {
        Value key = new Value(primaryKeyValue.toString());
        Value value = templateManager.getDataFromTemplateIndex(templateId, key);
        if (value == null) {
            return null;
        }

        return deserializeData(value.getData());
    }

    private byte[] serializeData(TemplateDataRow dataRow) throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(bos)) {
            oos.writeObject(dataRow);
            return bos.toByteArray();
        }
    }

    private TemplateDataRow deserializeData(byte[] data) throws IOException, ClassNotFoundException {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(bis)) {
            return (TemplateDataRow) ois.readObject();
        }
    }
}
